home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / VELENG10.ZIP / DATABASE.C < prev    next >
C/C++ Source or Header  |  1997-07-27  |  17KB  |  730 lines

  1. // ****************************************************************************
  2. // *                                                                          *
  3. // *                      Velena Source Code V1.0                             *
  4. // *                   Written by Giuliano Bertoletti                         *
  5. // *       Based on the knowledged approach of Louis Victor Allis             *
  6. // *   Copyright (C) 1996-97 by Giuliano Bertoletti & GBE 32241 Software PR   *
  7. // *                                                                          *
  8. // ****************************************************************************
  9.  
  10. // Portable engine version.
  11. // read the README file for further informations.
  12.  
  13. // ==========================================================================
  14.  
  15.  
  16. #include <stdio.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <malloc.h>
  20.  
  21. #include "connect4.h"
  22. #include "con4vals.h"
  23. #include "rules.h"
  24. #include "pnsearch.h"
  25. #include "proto.h"
  26.  
  27. #define DATABASEFILE    "openbook.cn4"
  28. #define DATABASEBACKUP  "openbook.bak"
  29. #define SHIPDISKFILE    "tempship.$$$"
  30. #define BUFSIZE         0x4000
  31.  
  32. struct dbtree *mmnode;
  33.  
  34. extern unsigned short *myscreen;
  35.  
  36. unsigned char blk[12],position[64],tpos[64];
  37. long blocks_wr,added_blocks,unused_blocks;
  38.  
  39. void expand_block(unsigned char *blk,unsigned char *pss)
  40.     {
  41.     pss[ELM(0,0)]=(blk[0+0*2]>>6)&0x03;
  42.     pss[ELM(1,0)]=(blk[0+0*2]>>4)&0x03;
  43.     pss[ELM(2,0)]=(blk[0+0*2]>>2)&0x03;
  44.     pss[ELM(3,0)]=(blk[0+0*2]   )&0x03;
  45.     pss[ELM(4,0)]=(blk[1+0*2]>>6)&0x03;
  46.     pss[ELM(5,0)]=(blk[1+0*2]>>4)&0x03;
  47.     pss[ELM(6,0)]=(blk[1+0*2]>>2)&0x03;
  48.     pss[ELM(7,0)]=0xff;
  49.  
  50.     pss[ELM(0,1)]=(blk[0+1*2]>>6)&0x03;
  51.     pss[ELM(1,1)]=(blk[0+1*2]>>4)&0x03;
  52.     pss[ELM(2,1)]=(blk[0+1*2]>>2)&0x03;
  53.     pss[ELM(3,1)]=(blk[0+1*2]   )&0x03;
  54.     pss[ELM(4,1)]=(blk[1+1*2]>>6)&0x03;
  55.     pss[ELM(5,1)]=(blk[1+1*2]>>4)&0x03;
  56.     pss[ELM(6,1)]=(blk[1+1*2]>>2)&0x03;
  57.     pss[ELM(7,1)]=0xff;
  58.  
  59.     pss[ELM(0,2)]=(blk[0+2*2]>>6)&0x03;
  60.     pss[ELM(1,2)]=(blk[0+2*2]>>4)&0x03;
  61.     pss[ELM(2,2)]=(blk[0+2*2]>>2)&0x03;
  62.     pss[ELM(3,2)]=(blk[0+2*2]   )&0x03;
  63.     pss[ELM(4,2)]=(blk[1+2*2]>>6)&0x03;
  64.     pss[ELM(5,2)]=(blk[1+2*2]>>4)&0x03;
  65.     pss[ELM(6,2)]=(blk[1+2*2]>>2)&0x03;
  66.     pss[ELM(7,2)]=0xff;
  67.  
  68.     pss[ELM(0,3)]=(blk[0+3*2]>>6)&0x03;
  69.     pss[ELM(1,3)]=(blk[0+3*2]>>4)&0x03;
  70.     pss[ELM(2,3)]=(blk[0+3*2]>>2)&0x03;
  71.     pss[ELM(3,3)]=(blk[0+3*2]   )&0x03;
  72.     pss[ELM(4,3)]=(blk[1+3*2]>>6)&0x03;
  73.     pss[ELM(5,3)]=(blk[1+3*2]>>4)&0x03;
  74.     pss[ELM(6,3)]=(blk[1+3*2]>>2)&0x03;
  75.     pss[ELM(7,3)]=0xff;
  76.  
  77.     pss[ELM(0,4)]=(blk[0+4*2]>>6)&0x03;
  78.     pss[ELM(1,4)]=(blk[0+4*2]>>4)&0x03;
  79.     pss[ELM(2,4)]=(blk[0+4*2]>>2)&0x03;
  80.     pss[ELM(3,4)]=(blk[0+4*2]   )&0x03;
  81.     pss[ELM(4,4)]=(blk[1+4*2]>>6)&0x03;
  82.     pss[ELM(5,4)]=(blk[1+4*2]>>4)&0x03;
  83.     pss[ELM(6,4)]=(blk[1+4*2]>>2)&0x03;
  84.     pss[ELM(7,4)]=0xff;
  85.  
  86.     pss[ELM(0,5)]=(blk[0+5*2]>>6)&0x03;
  87.     pss[ELM(1,5)]=(blk[0+5*2]>>4)&0x03;
  88.     pss[ELM(2,5)]=(blk[0+5*2]>>2)&0x03;
  89.     pss[ELM(3,5)]=(blk[0+5*2]   )&0x03;
  90.     pss[ELM(4,5)]=(blk[1+5*2]>>6)&0x03;
  91.     pss[ELM(5,5)]=(blk[1+5*2]>>4)&0x03;
  92.     pss[ELM(6,5)]=(blk[1+5*2]>>2)&0x03;
  93.     pss[ELM(7,5)]=0xff;
  94.  
  95.     memset(&pss[48],0xff,16);
  96.     }
  97.  
  98. void collapse_position(unsigned char *mypos,unsigned char *blk)
  99.     {
  100.     short y;
  101.  
  102.     for(y=0;y<BOARDY;y++)
  103.         {
  104.         blk[0+y*2]=((mypos[ELM(0,y)]&0x03)<<6)|
  105.                    ((mypos[ELM(1,y)]&0x03)<<4)|
  106.                    ((mypos[ELM(2,y)]&0x03)<<2)|
  107.                    ((mypos[ELM(3,y)]&0x03)   );
  108.  
  109.         blk[1+y*2]=((mypos[ELM(4,y)]&0x03)<<6)|
  110.                    ((mypos[ELM(5,y)]&0x03)<<4)|
  111.                    ((mypos[ELM(6,y)]&0x03)<<2)| 0x03;
  112.         }
  113.     }
  114.  
  115. short unused_position(unsigned char *ds,unsigned char *bd,short cancel_sym)
  116.     {
  117.     short x,y,flag=NO;
  118.  
  119.     /*return NO;*/
  120.  
  121.     switch(cancel_sym)
  122.         {
  123.         case NO:
  124.             for(y=0;y<BOARDY && !flag;y++)
  125.                 for(x=0;x<BOARDX && !flag;x++)
  126.                     if(bd[ELM(x,y)]!=EMPTY && bd[ELM(x,y)]!=ds[ELM(x,y)] &&
  127.                        bd[ELM(BOARDX-x-1,y)]!=EMPTY && bd[ELM(BOARDX-x-1,y)]!=ds[ELM(x,y)]) flag=YES;
  128.             break;
  129.  
  130.         case YES:
  131.             for(y=0;y<BOARDY && !flag;y++)
  132.                 for(x=0;x<BOARDX && !flag;x++)
  133.                     if(bd[ELM(x,y)]!=EMPTY && bd[ELM(x,y)]!=ds[ELM(x,y)]) flag=YES;
  134.             break;
  135.         }
  136.     return flag;
  137.     }
  138.  
  139. short test_dbtree_position(struct dbtree *root,unsigned char *mypos)
  140.     {
  141.     short cmp;
  142.  
  143.     if(!root) return 0;
  144.  
  145.     expand_block(root->cpos,tpos);
  146.  
  147.     cmp=bin_compare(tpos,mypos);
  148.     if(cmp<0) return test_dbtree_position(root->lson,mypos);
  149.     else if(cmp>0) return test_dbtree_position(root->rson,mypos);
  150.  
  151.     return root->value;
  152.     }
  153.  
  154. void add_dbtree(struct dbtree *root,unsigned char *mypos,short value)
  155.     {
  156.     short cmp;
  157.  
  158.     if(!root) fatal_error("Tryied to build an unallocated tree!");
  159.  
  160.     expand_block(root->cpos,tpos);
  161.     cmp=bin_compare(tpos,mypos);
  162.     if(cmp<0)
  163.         {
  164.         if(root->lson) add_dbtree(root->lson,mypos,value);
  165.         else
  166.             {
  167.             root->lson=(struct dbtree *)malloc(sizeof(struct dbtree));
  168.             if(!root->lson) fatal_error("Not enough memory");
  169.  
  170.             root->lson->parent=root;
  171.             root->lson->lson=NULL;
  172.             root->lson->rson=NULL;
  173.             root->lson->value=value;
  174.             root->lson->stacked=NO;
  175.  
  176.             collapse_position(mypos,root->lson->cpos);
  177.             }
  178.         }
  179.     else if(cmp>0)
  180.         {
  181.         if(root->rson) add_dbtree(root->rson,mypos,value);
  182.         else
  183.             {
  184.             root->rson=(struct dbtree *)malloc(sizeof(struct dbtree));
  185.             if(!root->rson) fatal_error("Not enough memory");
  186.  
  187.             root->rson->parent=root;
  188.             root->rson->lson=NULL;
  189.             root->rson->rson=NULL;
  190.             root->rson->value=value;
  191.             root->rson->stacked=NO;
  192.  
  193.             collapse_position(mypos,root->rson->cpos);
  194.             }
  195.         }
  196.  
  197.     return;
  198.     }
  199.  
  200. void my_add_dbtree(struct dbtree *root,unsigned char *mypos,short value,long posit)
  201.     {
  202.     short cmp;
  203.  
  204.     if(!root) fatal_error("Tryied to build an unallocated tree!");
  205.  
  206.     expand_block(root->cpos,tpos);
  207.  
  208.     cmp=bin_compare(tpos,mypos);
  209.     if(cmp<0)
  210.         {
  211.         if(root->lson) my_add_dbtree(root->lson,mypos,value,posit);
  212.         else
  213.             {
  214.             root->lson=(struct dbtree *)&mmnode[posit];
  215.             if(!root->lson) fatal_error("Not enough memory");
  216.  
  217.             root->lson->parent=root;
  218.             root->lson->lson=NULL;
  219.             root->lson->rson=NULL;
  220.             root->lson->value=value;
  221.             root->lson->stacked=YES;
  222.  
  223.             collapse_position(mypos,root->lson->cpos);
  224.             }
  225.         }
  226.     else if(cmp>0)
  227.         {
  228.         if(root->rson) my_add_dbtree(root->rson,mypos,value,posit);
  229.         else
  230.             {
  231.             root->rson=(struct dbtree *)&mmnode[posit];
  232.             if(!root->rson) fatal_error("Not enough memory");
  233.  
  234.             root->rson->parent=root;
  235.             root->rson->lson=NULL;
  236.             root->rson->rson=NULL;
  237.             root->rson->value=value;
  238.             root->rson->stacked=YES;
  239.  
  240.             collapse_position(mypos,root->rson->cpos);
  241.             }
  242.         }
  243.  
  244.     return;
  245.     }
  246.  
  247. struct dbtree *init_dbase(unsigned char *currposit,short cancel_sym)
  248.     {
  249.     FILE *h1,*h2;
  250.     struct dbtree *dbroot;
  251.     long posit,size,tsize,rsize;
  252.     short block,value,x;
  253.  
  254.     printf("\n");
  255.     printf("Initializing database...\n");
  256.  
  257.     mmnode=NULL;
  258.  
  259.     dbroot=(struct dbtree *)malloc(sizeof(struct dbtree));
  260.     if(!dbroot) fatal_error("Not enough memory to handle data base!");
  261.  
  262.     memset(dbroot->cpos,0xff,12);
  263.  
  264.     unused_blocks=0L;
  265.  
  266.     dbroot->parent=NULL;
  267.     dbroot->lson=NULL;
  268.     dbroot->rson=NULL;
  269.     dbroot->value=0x7fff;
  270.  
  271.     h1=fopen(DATABASEFILE,"rb");
  272.     if(!h1) goto SKIP_FILE_LOADING;
  273.  
  274.     size=tsize=fileln(h1);
  275.     if((size%14)!=0) fatal_error("Invalid data received!");
  276.  
  277.     printf("Total number of blocks in data base: %ld (file size: %ld)\n",size/14,size);
  278.  
  279.     for(x=0;x<79;x++)
  280.         myscreen[x]=0x7e20;
  281.  
  282.     h2=fopen(SHIPDISKFILE,"wb");
  283.     if(!h2) fatal_error("Cannot write to hard disk!");
  284.  
  285.     printf("Looking for unused blocks...\n");
  286.  
  287.     while(size>0)
  288.         {
  289.         fread(blk,1,12,h1);
  290.         value=((short)getc(h1));
  291.         value+=((short)getc(h1)<<8);
  292.         expand_block(blk,position);
  293.  
  294.         if(unused_position(position,currposit,cancel_sym))
  295.             {
  296.             unused_blocks++;
  297.             fwrite(blk,1,12,h2);
  298.             putc(value&0xff,h2);
  299.             putc(value>>8,h2);
  300.             }
  301.  
  302.         for(x=0;x<(80L*(tsize-size))/tsize;x++)
  303.             myscreen[x]=0x4e20;
  304.  
  305.         size-=14;
  306.         }
  307.  
  308.     fclose(h2);
  309.     printf("%ld unused blocks shipped to disk (file size: %ld)\n",unused_blocks,unused_blocks*14L);
  310.  
  311.     fseek(h1,0L,SEEK_SET);
  312.     size=tsize;
  313.     rsize=tsize-unused_blocks*14L;
  314.  
  315.     if(rsize==0)
  316.         {
  317.         fclose(h1);
  318.         goto SKIP_FILE_LOADING;
  319.         }
  320.  
  321.     mmnode=(struct dbtree *)malloc((rsize/14)*sizeof(struct dbtree));
  322.     if(!mmnode) fatal_error("Cannot allocate the big memory block, darn!\n");
  323.  
  324.     printf("%ld bytes successfully allocated as big memory block\n",
  325.             (rsize/14)*sizeof(struct dbtree));
  326.  
  327.     posit=0L;
  328.     while(size>0)
  329.         {
  330.         fread(blk,1,12,h1);
  331.         value=((short)getc(h1));
  332.         value+=((short)getc(h1)<<8);
  333.         expand_block(blk,position);
  334.  
  335.         if(!unused_position(position,currposit,cancel_sym))
  336.             {
  337.             my_add_dbtree(dbroot,position,value,posit);
  338.             posit++;
  339.             }
  340.  
  341.         if((posit&0x03ff)==0)
  342.             printf("Loading positions data base from disk... : %ld  (unused: %ld)\r",posit,unused_blocks);
  343.  
  344.         size-=14;
  345.  
  346.         for(x=0;x<(80L*(tsize-size))/tsize;x++)
  347.             myscreen[x]=0x1e20;
  348.         }
  349.  
  350.     fclose(h1);
  351.     printf("Loading positions data base from disk... : %ld  (unused: %ld)\n",posit,unused_blocks);
  352.     printf("\n");
  353.  
  354.     if(posit+unused_blocks!=tsize/14) fatal_error("Something went wrong!");
  355.  
  356.     SKIP_FILE_LOADING:
  357.     return dbroot;
  358.     }
  359.  
  360. void my_free_dbtree(struct dbtree *root)
  361.     {
  362.     if(root->lson) my_free_dbtree(root->lson);
  363.     if(root->rson) my_free_dbtree(root->rson);
  364.     if(!root->stacked) free(root);
  365.     }
  366.  
  367. void free_dbtree(struct dbtree *root)
  368.     {
  369.     my_free_dbtree(root);
  370.     if(mmnode) free(mmnode);
  371.     }
  372.  
  373. void flush_tree(struct dbtree *root,FILE *h1)
  374.     {
  375.     if(!root) return;
  376.  
  377.     if(root->cpos[0]!=0xff)
  378.         {
  379.         fwrite(root->cpos,1,12,h1);
  380.         putc(root->value&0xff,h1);
  381.         putc(root->value>>8,h1);
  382.         blocks_wr++;
  383.  
  384.         if((blocks_wr&0x03ff)==0)
  385.             printf("Blocks written %ld\r",blocks_wr);
  386.         }
  387.  
  388.     flush_tree(root->lson,h1);
  389.     flush_tree(root->rson,h1);
  390.     }
  391.  
  392. void flush_dbtree(struct dbtree *root)
  393.     {
  394.     long bb=0L;
  395.     FILE *h1,*h2;
  396.  
  397.     blocks_wr=0L;
  398.  
  399.     h1=fopen(DATABASEFILE,"wb");
  400.     if(!h1) fatal_error("Cannot write file to disk!");
  401.  
  402.     printf("Writing positions to disk...\n");
  403.     flush_tree(root,h1);
  404.     printf("Blocks written %ld\r",blocks_wr);
  405.  
  406.     h2=fopen(SHIPDISKFILE,"rb");
  407.     if(h2)
  408.         {
  409.         short byte;
  410.         while((byte=getc(h2))!=EOF)
  411.             {
  412.             putc(byte,h1);
  413.             bb++;
  414.             if(bb%(1024*14)==0)
  415.                 printf("Blocks written %ld + %ld = %ld\r",blocks_wr,bb/14,blocks_wr+bb/14);
  416.             }
  417.         fclose(h2);
  418.         printf("Blocks written %ld + %ld = %ld\r",blocks_wr,bb/14,blocks_wr+bb/14);
  419.         }
  420.     fclose(h1);
  421.     printf("\n");
  422.     }
  423.  
  424. void copy_dbtree()
  425.     {
  426.     long len;
  427.     unsigned char *buffer;
  428.     short block;
  429.     FILE *h1,*h2;
  430.  
  431.     h1=fopen(DATABASEFILE,"rb");
  432.     if(!h1)
  433.         {
  434.         printf("Creating data base file...\n");
  435.         return;
  436.         }
  437.  
  438.     h2=fopen(DATABASEBACKUP,"wb");
  439.     if(!h2) fatal_error("Error handling data base files...");
  440.  
  441.     buffer=(unsigned char *)malloc(BUFSIZE);
  442.     if(!buffer) fatal_error("Cannot allocate temporary buffer!");
  443.  
  444.     printf("Backing up data base file...\n");
  445.     len=fileln(h1);
  446.     while(len>0)
  447.         {
  448.         block=(short)min(len,BUFSIZE);
  449.         fread(buffer,1,block,h1);
  450.         fwrite(buffer,1,block,h2);
  451.         len-=block;
  452.         }
  453.  
  454.     free(buffer);
  455.     fclose(h1);
  456.     fclose(h2);
  457.     }
  458.  
  459. void update_dbtree(struct bintree *treeroot,struct dbtree *dbroot,short side)
  460.     {
  461.     short vl;
  462.  
  463.     if(treeroot->lson) update_dbtree(treeroot->lson,dbroot,side);
  464.     if(treeroot->rson) update_dbtree(treeroot->rson,dbroot,side);
  465.  
  466.     if(side==WHITE)
  467.         {
  468.         if(treeroot->node->value==PROVED) vl=PROVED;
  469.         else vl=DISPROVED;
  470.         }
  471.     else
  472.         {
  473.         if(treeroot->node->value==PROVED) vl=DISPROVED;
  474.         else vl=PROVED;
  475.         }
  476.  
  477.     if(treeroot->node->value!=UNKNOWN && !treeroot->node->direct)
  478.         add_dbtree(dbroot,treeroot->node->square,vl);
  479.     }
  480.  
  481. /* --------------------------------------------------------------------- */
  482.  
  483. long myrandom(long maxval)
  484.     {
  485.     return(long)(((double)rand()*maxval)/32768.0);
  486.     }
  487.  
  488. void shuffle(void)
  489.     {
  490.     long size,nodes,pv,aq;
  491.         unsigned char *p,temp[14];
  492.     FILE *h1;
  493.  
  494.     h1=fopen(DATABASEFILE,"rb");
  495.     if(!h1) fatal_error("Could not find opening book");
  496.  
  497.     size=fileln(h1);
  498.     nodes=size/14;
  499.  
  500.         printf("Memory required: %ld bytes\n",14L*nodes*sizeof(unsigned char));
  501.         p=(unsigned char *)malloc(14L*nodes*sizeof(unsigned char));
  502.     if(!p) fatal_error("Not enough memory !");
  503.  
  504.     printf("File size = %ld bytes\n",size);
  505.     printf("%ld nodes detected...\n",nodes);
  506.     printf("Loading...\n");
  507.  
  508.     for(pv=0L;pv<nodes;pv++)
  509.                 fread(&p[14L*pv],1,14,h1);
  510.  
  511.     fclose(h1);
  512.  
  513.     h1=fopen(DATABASEFILE,"wb");
  514.     if(!h1) fatal_error("Cannot write shuffled opening book");
  515.  
  516.     printf("Now shuffling and rewriting nodes...\n");
  517.     while(pv>0)
  518.         {
  519.         aq=myrandom(pv);
  520.  
  521.                 memcpy(temp,&p[14L*aq],14);
  522.                 memcpy(&p[14L*aq],&p[14L*(pv-1)],14);
  523.                 memcpy(&p[14L*(pv-1)],temp,14);
  524.  
  525.                 fwrite(&p[14L*(pv-1)],1,14,h1);
  526.         pv--;
  527.         }
  528.  
  529.     fclose(h1);
  530.     free(p);
  531.  
  532.     printf("Done!\n\n");
  533.     }
  534.  
  535. /* ----------------------------------------------------------------- */
  536.  
  537. void free_small_tree(struct small_tree *root)
  538.     {
  539.     if(root->lson) free_small_tree(root->lson);
  540.     if(root->rson) free_small_tree(root->rson);
  541.     free(root);
  542.     }
  543.  
  544. void flush_smtree(struct small_tree *root,FILE *h1)
  545.     {
  546.     if(!root) return;
  547.  
  548.     if(root->buffer[0]!=0xff)
  549.         {
  550.         fwrite(root->buffer,1,14,h1);
  551.         blocks_wr++;
  552.         if((blocks_wr&0x03ff)==0)
  553.             printf("Blocks written %ld\r",blocks_wr);
  554.         }
  555.  
  556.     if(my_random(256)&1)
  557.         {
  558.         flush_smtree(root->lson,h1);
  559.         flush_smtree(root->rson,h1);
  560.         }
  561.     else
  562.         {
  563.         flush_smtree(root->rson,h1);
  564.         flush_smtree(root->lson,h1);
  565.         }
  566.     }
  567.  
  568. void flush_small_tree(struct small_tree *root)
  569.     {
  570.     FILE *h1;
  571.  
  572.     blocks_wr=0L;
  573.  
  574.     h1=fopen(DATABASEFILE,"wb");
  575.     if(!h1) fatal_error("Cannot write file to disk!");
  576.  
  577.     printf("Writing positions to disk...\n");
  578.     flush_smtree(root,h1);
  579.     printf("Blocks written %ld\r",blocks_wr);
  580.     fclose(h1);
  581.     printf("\n\n");
  582.     }
  583.  
  584. short compare_small_tree(unsigned char *b1,unsigned char *b2)
  585.     {
  586.     short x;
  587.  
  588.     for(x=0;x<14;x++)
  589.         {
  590.         if(b1[x]<b2[x]) return -1;
  591.         if(b2[x]<b1[x]) return  1;
  592.         }
  593.  
  594.     return 0;
  595.     }
  596.  
  597. struct small_tree *check_and_add(struct small_tree *root,unsigned char *buffer)
  598.     {
  599.     if(!root)
  600.         {
  601.         added_blocks++;
  602.  
  603.         if((added_blocks&0x3ff)==0)
  604.             printf("Total blocks number %6ld\r",added_blocks);
  605.  
  606.         root=(struct small_tree *)malloc(sizeof(struct small_tree));
  607.         if(!root) fatal_error("Not enough memory to merge files");
  608.  
  609.         root->lson=NULL;
  610.         root->rson=NULL;
  611.         memcpy(root->buffer,buffer,14);
  612.         }
  613.  
  614.     else
  615.         {
  616.         short cmp;
  617.  
  618.         cmp=compare_small_tree(root->buffer,buffer);
  619.         if(cmp<0)
  620.             {
  621.             root->lson=check_and_add(root->lson,buffer);
  622.             root->lson->parent=root;
  623.             }
  624.  
  625.         else if(cmp>0)
  626.             {
  627.             root->rson=check_and_add(root->rson,buffer);
  628.             root->rson->parent=root;
  629.             }
  630.         }
  631.  
  632.     return root;
  633.     }
  634.  
  635. short merge_file(char *name)
  636.     {
  637.     unsigned char buffer[14];
  638.     long size,diff;
  639.     FILE *h1,*h2;
  640.     struct small_tree *root;
  641.  
  642.     h1=fopen(DATABASEFILE,"rb");
  643.     if(!h1) return NO;
  644.  
  645.     h2=fopen(name,"rb");
  646.     if(!h2)
  647.         {
  648.         fclose(h1);
  649.         return NO;
  650.         }
  651.  
  652.     added_blocks=-1L;
  653.  
  654.     memset(buffer,0xff,14);
  655.     root=check_and_add(NULL,buffer);
  656.  
  657.     size=fileln(h1);
  658.     if((size%14)!=0) fatal_error("Invalid database file");
  659.  
  660.     while(size>0)
  661.         {
  662.         fread(buffer,1,14,h1);
  663.         check_and_add(root,buffer);
  664.         size-=14;
  665.         }
  666.  
  667.     diff=-added_blocks;
  668.  
  669.     size=fileln(h2);
  670.     if((size%14)!=0) fatal_error("Invalid file to merge");
  671.  
  672.     while(size>0)
  673.         {
  674.         fread(buffer,1,14,h2);
  675.         check_and_add(root,buffer);
  676.         size-=14;
  677.         }
  678.  
  679.     fclose(h1);
  680.     fclose(h2);
  681.  
  682.     diff+=added_blocks;
  683.  
  684.     printf("Total blocks number %6ld (really added %ld)\n",added_blocks,diff);
  685.  
  686.     copy_dbtree();
  687.     flush_small_tree(root);
  688.     free_small_tree(root);
  689.  
  690.     shuffle();
  691.  
  692.     return 1;
  693.     }
  694.  
  695. void merge()
  696.     {
  697.     unsigned short key;
  698.     char filename[255];
  699.  
  700.     printf("Enter name of file to merge: ");
  701.     gets(filename);
  702.  
  703.     printf("\n");
  704.     printf("Sure you want to merge '%s' ? (Y/N)\n\n",filename);
  705.  
  706.     do
  707.         {
  708.         key=readkey();
  709.         } while(key!='n' && key!='y');
  710.  
  711.     if(key=='y')
  712.         {
  713.         if(merge_file(filename))
  714.             printf("Everything went ok!\n");
  715.  
  716.         else printf("Something went wrong, perhaps file has not been found!\n");
  717.         }
  718.     else printf("Nothing has been done...\n");
  719.  
  720.     printf("\n");
  721.     printf("Any key to continue!\n");
  722.     while(readkey()==0);
  723.     }
  724.  
  725. void erase_temp_file()
  726.     {
  727.     unlink(SHIPDISKFILE);
  728.     }
  729.  
  730.